package com.rfsp.mcp.service.interfaceclient;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.rfsp.common.base.BaseService;
import com.rfsp.common.base.ResultVO;
import com.rfsp.common.util.*;
import com.rfsp.mcp.enums.TransCodeEnum;
import com.rfsp.mcp.feign.McpRelayFeign;
import com.rfsp.mcp.mapper.*;
import com.rfsp.mcp.pojo.dto.FlowDTO;
import com.rfsp.mcp.pojo.dto.MiAccountInfoDto;
import com.rfsp.mcp.pojo.dto.MiPayInfoDto;
import com.rfsp.mcp.pojo.dto.OrgSubjectInfoDto;
import com.rfsp.mcp.pojo.po.*;
import com.rfsp.mcp.pojo.vo.*;
import com.rfsp.mcp.service.FlowService;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URI;
import java.util.*;

@Service
public class WSMiAccountService extends BaseService<MiAccountPO>{
    public Logger logger = LoggerFactory.getLogger(WSMiAccountService.class);
    @Autowired
    private PfmMapper pfmMapper;
    @Autowired
    private WsItfMapper wsItfMapper;
    @Autowired
    McpRelayFeign feign;
    @Autowired
    FlowService flowService;

    @Autowired
    private MCPWsKeyMapper mCPWsKeyMapper;

    @Value("${mcp.file-path-paylog}")
    private String filePath;

    @Transactional
    public ResultVO<String> queryMiAccountInfo(MiAccountInfoDto miAccountInfoDto){
        FlowDTO response_flow=new FlowDTO();
            //-----业务执行-----
            //1、通过医保平台ID，获取医保平台信息
            String pfmOrgCode = "";//医保系统的统一社会信用代码
            String edType = "";//加密类型：0表示不加密，1表示SM2加密
            String orgpub = "";//ORG_PUB对接系统加密公钥
            String plfpri = "";//PLF_PRI平台解密私钥
            String transCode = TransCodeEnum.M1004.getKey();//接口代码
            String msgId = UUID.randomUUID().toString();//请求流水号
        try{
            String sendDate = DateUtil.dateFormatStr("yyyyMMdd");//接口请求日期
            String sendTime = DateUtil.dateFormatStr("HHmmss");//接口请求时间
            if(miAccountInfoDto==null){
                return ResultVO.fail("orgDirectoryDto参数不能为空");
            }else if(miAccountInfoDto.getPfmId()==null){
                return ResultVO.fail("PfmId不能为空");
            }else {
                PfmPO pfmPO = pfmMapper.selectByPrimaryKey(miAccountInfoDto.getPfmId());
                if(pfmPO!=null){
                    pfmOrgCode = pfmPO.getPfmOrgCode();//医保系统的统一社会信用代码
                    edType = pfmPO.getEdType();//加密类型：0表示不加密，1表示SM2加密
                }else{
                    return ResultVO.fail("PfmId参数值错误，请检查");
                }
            }
            if(miAccountInfoDto.getMiOrgCode()==null){
                return ResultVO.fail("miOrgCode不能为空");
            }
            logger.error("edType==============================="+edType);
            //判断请求是否需要加密解密
            if(!StringUtils.isEmpty(edType)&&"1".equals(edType)){//如需要加密
                //如果需要加密,则获取对应的 公私钥
                Map<String, Object> wsKeyPara = new HashMap<String, Object>();
                wsKeyPara.put("fk_org_id", miAccountInfoDto.getPfmId());//医保局平台id
                List<Map<String, Object>> wsKeylist = mCPWsKeyMapper.getWsKey(wsKeyPara);
                if(null != wsKeylist && !wsKeylist.isEmpty()) {
                    Map<String, Object> map = wsKeylist.get(0);
                    orgpub = map.get("orgpub")==null?"":map.get("orgpub").toString();//ORG_PUB对接系统加密公钥
                    plfpri = map.get("plfpri")==null?"":map.get("plfpri").toString();//PLF_PRI平台解密私钥
                    if(StringUtils.isEmpty(orgpub)||StringUtils.isEmpty(plfpri)){
                        return ResultVO.fail("如需要SM2加密，对接系统加密公钥和平台解密私钥不能为空值，请检查");
                    }
                }else{
                    return ResultVO.fail("未查到该平台SM2加密信息，请检查");
                }


            }


            //组装json请求报文
            ObjectMapper objectMapper = new ObjectMapper();
            ObjectNode json = objectMapper.createObjectNode();
            json.put("pfmOrgCode", pfmOrgCode);
            json.put("transCode", transCode);
            json.put("msgId", msgId);
            json.put("sendDate", sendDate);
            json.put("sendTime", sendTime);
            json.put("fixmedinsCode", miAccountInfoDto.getMiOrgCode());
            json.put("mark1", "");
            json.put("mark2", "");
            json.put("mark3", "");
            // 转换为字符串
            String jsonString = json.toString();

            //2、获取接口配置管理中医保局平台URL和转发应用URL
            String forWordUrl = "";//转发程序URL
            URI baseUri = null;
            String pfmUrl = "";//医保局平台系统url
            String status = "";//接口状态
            Map<String, Object> para = new HashMap<String, Object>();
            para.put("org_id", miAccountInfoDto.getPfmId());//医保平台id
            para.put("code", TransCodeEnum.M1004.getKey());//接口代码
            List<Map<String, Object>> list = wsItfMapper.getBizIdByItf(para);
            if(null != list && !list.isEmpty()){
                Map<String, Object> map = list.get(0);
                pfmUrl = map.get("uri")==null?"":map.get("uri").toString();//医保局平台URL
                if(StringUtils.isEmpty(pfmUrl)){
                    return ResultVO.fail("接口配置信息表中，医保局平台URL值为空");
                }
                forWordUrl = map.get("url")==null?"":map.get("url").toString();//转发系统URL
                if(StringUtils.isEmpty(forWordUrl)){
                    return ResultVO.fail("接口配置信息表中，转发系统URL值为空");
                }
                status = map.get("status")==null?"":map.get("status").toString();//接口状态
                if(StringUtils.isEmpty(status)){
                    return ResultVO.fail("接口配置信息表中，接口状态值为空");
                }else if(!"1".equals(status)){
                    return ResultVO.fail("接口配置信息表中，接口状态值为停用");
                }
                baseUri = new URI(forWordUrl);
            }else{
                return ResultVO.fail("没有接口配置信息");
            }

            //3、先生成一条请求流水数据信息和将请求报文json文件落地
            FlowDTO request_flow=new FlowDTO();
            request_flow.setAid(getAID());//辅助标识，防止修改主键ID查询的漏洞，不保证唯一
            request_flow.setCurrentNo(msgId);//请求流水号
            request_flow.setTransCode(TransCodeEnum.M1004.getKey());
            request_flow.setStatus("4");//处理成功
            request_flow.setInFlag("1");//请求方向 1：请求
            request_flow.setOrgNo(pfmOrgCode);//医保局平台组织机构代码
            request_flow.setOperation("0");//接口业务方向：0平台到医保系统
            request_flow.setPfmId(miAccountInfoDto.getPfmId());
            request_flow.setLogId(miAccountInfoDto.getLogId());//查询记录信息Log

            //以接口请求方向代码+请求流水号（唯一值）作为文件名
            String request_fileName=request_flow.getInFlag()+request_flow.getCurrentNo()+".txt";
            String request_filePath = this.filePath.replaceFirst("date/", StringUtil.dateToString(new Date(), "yyyy/MM/dd/"));
            request_flow.setContEncript(request_filePath+request_fileName);//文件路径+名称
            request_flow.setSdate(new Date());
            request_flow.setStime(new Date());
            request_flow.setEdate(new Date());
            request_flow.setEtime(new Date());
            //存储落地json文件
            FileUtil.create(request_filePath,request_fileName,jsonString,false);
            //保存接口流水表
            createFlow(request_flow);

            //4、调用转发服务进行查询，返回json报文
            OrgYbjMiAccountVO vo= null;
            List<OrgYbjMiAccountVO> lData = new ArrayList<>();

            //判断请求是否需要sm2加密解密
            McpInterfaceResultVO resultVO = null;
            if(!StringUtils.isEmpty(edType)&&"1".equals(edType)){
                resultVO = feign.queryMiAccountInfo(baseUri,pfmUrl,jsonString,edType,orgpub,plfpri);
            }else{
                resultVO = feign.queryMiAccountInfo(baseUri,pfmUrl,jsonString,edType,"","");
            }

            //5、插入响应信息接口流水和报文文件落地（成功或失败都需要插流水和落文件）

            response_flow.setAid(getAID());//辅助标识，防止修改主键ID查询的漏洞，不保证唯一
            response_flow.setCurrentNo(msgId);//请求流水号
            response_flow.setTransCode(TransCodeEnum.M1004.getKey());
            response_flow.setStatus("4");//处理成功
            response_flow.setInFlag("2");//请求方向 2:响应
            response_flow.setOrgNo(pfmOrgCode);//医保局平台组织机构代码
            response_flow.setOperation("1");//接口业务方向：1：医保系统到平台
            response_flow.setPfmId(miAccountInfoDto.getPfmId());
            response_flow.setLogId(miAccountInfoDto.getLogId());//查询记录信息Log
            /*//将请求参数报文中也加入到落地json文件中
            resultVO.setRequestJson(jsonString);*/
            ObjectMapper mapper = new ObjectMapper();
            String content="";
            try {
                content += mapper.writeValueAsString(resultVO);
            } catch (JsonProcessingException e) {
                logger.error(e.getMessage());
                e.printStackTrace();
            }
            content+="\n\n";
            //以接口响应方向+请求流水号（唯一值）作为文件名
            String response_fileName=response_flow.getInFlag()+response_flow.getCurrentNo()+".txt";
            String response_filePath = this.filePath.replaceFirst("date/", StringUtil.dateToString(new Date(), "yyyy/MM/dd/"));
            response_flow.setContEncript(response_filePath+response_fileName);//文件路径+名称
            response_flow.setSdate(new Date());
            response_flow.setStime(new Date());
            response_flow.setEdate(new Date());
            response_flow.setEtime(new Date());
            //存储落地json文件
            FileUtil.create(response_filePath,response_fileName,content,false);
            //保存接口流水表
            createFlow(response_flow);


        //6、----保存账户信息数据-----
        if(resultVO!=null&&resultVO.getMsg().equals("success")){
            String jsonResult = resultVO.getData();
            //判断返回的JSON是否包含数据
            if(!StringUtils.isEmpty(jsonResult)&&!JsonUtil.isEmptyJson(jsonResult)) {
                //获取账户信息数据
                lData = JsonUtil.toBeanList(jsonResult, OrgYbjMiAccountVO.class, "data");
                if(lData.size()>0){
                    vo = lData.get(0);
                }

                //存储医保局定点机构信息表名录信息
                //boolean isStorageStatus = true;//存储状态，当有一条失败时，就将流水表状态设置为失败，且在json文件中标出错误信息
                StringBuffer errBuffer = new StringBuffer();//如存在存储失败的记录，记录失败原因，写入到json文件中，且置流水表状态为失败
                if(vo!=null){
                    vo.setLogId(miAccountInfoDto.getLogId());//插入查询记录log_id
                    vo.setPfmId(miAccountInfoDto.getPfmId());//医保局平台ID
                    saveMiAccountData(vo,errBuffer);
                }
                //判断是否有存储失败的记录
                if(errBuffer.length()>0){
                    //1、变更流水表状态为失败
                    FlowPO queryPo=new FlowPO();
                    queryPo.setAid(response_flow.getAid());
                    queryPo.setPfmId(response_flow.getPfmId());
                    queryPo.setLogId(response_flow.getLogId());
                    List<FlowPO> listFlowPo = flowService.queryList(queryPo);
                    if(listFlowPo!=null&&listFlowPo.size()>0){
                        FlowPO po = listFlowPo.get(0);
                        po.setStatus("3");//处理失败
                        flowService.update(po);
                    }
                    //2、重写json文件，增加存储失败信息
                    ObjectMapper objectMapperAdd = new ObjectMapper();
                    File jsonFile = new File(response_flow.getContEncript());
                    try {
                        // 读取JSON文件到Map对象（或其他Java对象）
                        Map<String, Object> jsonMap = objectMapperAdd.readValue(jsonFile, Map.class);
                        // 修改Java对象（这里是Map）
                        jsonMap.put("isStoragefailed","failed");
                        jsonMap.put("storagefailedMsg",errBuffer.toString());
                        // 将修改后的对象写回JSON文件
                        objectMapper.writeValue(jsonFile, jsonMap); // 或者使用Files工具类覆盖原文件内容，例如：Files.write(Paths.get("path/to/your/data.json"), objectMapper.writeValueAsBytes(jsonMap));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return ResultVO.fail("同步医保账户信息失败");

                }
            }
               //-----执行成功-----
                return ResultVO.success("同步医保账户信息成功");

            }else{
                //请求医保局平台报文失败的，更新流水表信息为处理失败，异常内容就在落地的json文件中
                FlowPO queryPo=new FlowPO();
                queryPo.setAid(response_flow.getAid());
                queryPo.setPfmId(response_flow.getPfmId());
                queryPo.setLogId(response_flow.getLogId());
                List<FlowPO> listFlowPo = flowService.queryList(queryPo);
                if(listFlowPo!=null&&listFlowPo.size()>0){
                    FlowPO po = listFlowPo.get(0);
                    po.setStatus("3");//处理失败
                    flowService.update(po);
                }
                //向上层应用返回调用失败
                 logger.error("=====转发应用调用医保局平台接口服务失败=====");
                return ResultVO.fail("转发应用调用医保局平台接口服务失败");
            }
        }catch (Exception e){
            //1、变更流水表状态为失败
            if(!StringUtils.isEmpty(response_flow.getAid())) {
                FlowPO queryPo = new FlowPO();
                queryPo.setAid(response_flow.getAid());
                queryPo.setPfmId(response_flow.getPfmId());
                queryPo.setLogId(response_flow.getLogId());
                List<FlowPO> listFlowPo = flowService.queryList(queryPo);
                if (listFlowPo != null && listFlowPo.size() > 0) {
                    FlowPO po = listFlowPo.get(0);
                    po.setStatus("3");//处理失败
                    flowService.update(po);
                }
            }
            logger.error("=========同步医保账户信息失败:=============,{}",e);
            return ResultVO.fail("同步医保账户信息失败");
        }
    }


    @Transactional
    public void saveMiAccountData(OrgYbjMiAccountVO vo,StringBuffer errBuffer) throws Exception{
        MiAccountPO miAccountPO = new MiAccountPO();
        //循环保存
        try{
            //将报文各数据项转换为PO各属性值
            miAccountPO = this.makePo(vo);
            //保存账户信息
            this.save(miAccountPO);
        }catch (Exception e){
            //可以在这里记录错误日志，但不抛出异常，允许事务继续
            logger.error("=========医保账户信息存储失败:=============,{}",e);
            errBuffer.append(e.getMessage()).append("||");
        }

    }

    private Integer createFlow(FlowDTO dto){
        Integer count=flowService.create(dto);
        return count;
    }
    public String getAID() {
        String str = "1234567890qwertyuiopasdfghjklzxcvbnm";
        Random r = new Random();

        StringBuffer sb = new StringBuffer(16);

        for(int i=0;i<16;i++) {
            int index = r.nextInt(str.length());
            sb.append(str.charAt(index));
        }
        return sb.toString();
    }


    public MiAccountPO makePo(OrgYbjMiAccountVO vo) throws Exception {
        MiAccountPO miAccountPO = new MiAccountPO();
        try {
            //BeanUtils.copyProperties(vo,miPayPO);
            if(StringUtils.isEmpty(vo.getOrgNo())){
                throw new Exception("医疗机构代码值不能为空");
            }else{
                miAccountPO.setOrgNo(vo.getOrgNo());//医疗机构代码(必填项)
            }
            if(StringUtils.isEmpty(vo.getOrgName())){
                throw new Exception("医疗机构名称值不能为空");
            }else{
                miAccountPO.setOrgName(vo.getOrgName());//医疗机构名称(必填项)
            }

            miAccountPO.setOrgCode(vo.getOrgCode());/** 统一社会信用代码 */
            miAccountPO.setAccountName(vo.getAccountName());/** 银行开户名称 */
            miAccountPO.setAccountNo(vo.getAccountNo());/** 银行账号 */
            miAccountPO.setAccountBank(vo.getAccountBank());/** 开户银行 */
            miAccountPO.setRemark1(vo.getRemark1());//预留字段1
            miAccountPO.setRemark2(vo.getRemark2());//预留字段2
            miAccountPO.setRemark3(vo.getRemark3());//预留字段3
            miAccountPO.setRemark4(vo.getRemark4());//预留字段4
            miAccountPO.setRemark5(vo.getRemark5());//预留字段5
            miAccountPO.setRemark6(vo.getRemark6());//预留字段6
            miAccountPO.setRemark7(vo.getRemark7());//预留字段7
            miAccountPO.setRemark8(vo.getRemark8());//预留字段8
            miAccountPO.setRemark9(vo.getRemark9());//预留字段9
            miAccountPO.setRemark10(vo.getRemark10());//预留字段10

            //copy完，再补充其他字段项
            miAccountPO.setLogId(vo.getLogId());//查询记录表ID
            miAccountPO.setPfmId(vo.getPfmId());//医保局平台ID
            miAccountPO.setAid(getAID());/** 辅助标识，防止修改主键ID查询的漏洞，不保证唯一 */
            miAccountPO.setOptTime(new Date());//操作时间，页面操作更新时间
            miAccountPO.setCreateTime(new Date());//创建时间，接口插入记录时间
            miAccountPO.setUpdateTime(new Date());//接口更新时间

        }catch (Exception e){
            logger.error("=========makePo响应报文中存在属性值格式转换异常，请检查:=============,{}",e);
            throw new Exception("响应报文中存在属性值格式转换异常，请检查："+e.getMessage());
        }
        //return miAccountPO;
        return XssUtils.replaceXss(miAccountPO);
    }

}